package nie.ctrl;

import nie.bean.AncientPainting;
import nie.bean.Catalog;
import nie.bean.User;
import nie.dao.AncientPaintingDao;
import nie.dao.CatalogDao;
import nie.dao.UserDao;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.servlet.http.Part;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@WebServlet(name = "CenterController", value = "*.action")
@MultipartConfig
public class CenterController extends HttpServlet {
  @Override
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    request.setCharacterEncoding("UTF-8");
    response.setContentType("text/html;charset=utf-8");
    PrintWriter out = response.getWriter();
    HttpSession session = request.getSession();
    String action = request.getServletPath();
    action = action.substring(action.lastIndexOf('/') + 1, action.indexOf(".action"));
    if (action.equals("login")) {
      String un = request.getParameter("username");
      String pw = request.getParameter("password");
      String role = request.getParameter("role");
      User user = new User();
      user.setUsername(un);
      user.setPassword(pw);
      user.setRole(Integer.parseInt(role));
      UserDao userDao = new UserDao();
      // 验证用户是否存在，密码和角色是否匹配
      User target = userDao.checkUser(user);
      if (target != null) {
        // 登录成功
        session.setAttribute("user", target);
        AncientPaintingDao ancientPaintingDao = new AncientPaintingDao();
        List<AncientPainting> ancientPaintings = ancientPaintingDao.getAllAncientPaintings();
        request.setAttribute("ancientPaintings", ancientPaintings);
        if (role.equals("0")) {
          out.println("<script>location.href='userListAncientPainting.action';</script>");
        } else {
          CatalogDao catalogDao = new CatalogDao();
          List<Catalog> catalogs = catalogDao.getAllCatalogs();
          request.setAttribute("catalogs", catalogs);
          out.println("<script>location.href='adminListAncientPainting.action';</script>");
        }
      } else {
        // 登录失败
        // 找不到用户或用户名或密码错误，跳转到登录页面，并提示错误信息
        out.println("<script>alert('用户名或密码错误请重新登录');</script>");
        out.println("3秒后自动跳转到登录页面……");
        response.setHeader("Refresh", "3,url='login.jsp'");
      }
    } else if (action.equals("register")) {
      String un = request.getParameter("username");
      String pw = request.getParameter("password");
      String role = request.getParameter("role");
      String name = request.getParameter("name");
      String age = request.getParameter("age");
      UserDao ud = new UserDao();
      boolean flag = ud.findByUsername(un);
      // 用户如果为true，代表用户已存在，则跳转到登录页
      if (flag) {
        out.println("<script>alert('用户名已存在，请登录');</script>");
        out.println("马上去登录……");
        response.setHeader("Refresh", "1,url='login.jsp'");
      } else {
        // 如果注册的时候用户不存在，则保存用户信息到数据库
        User user = new User();
        user.setUsername(un);
        user.setPassword(pw);
        user.setRole(Integer.parseInt(role));
        user.setAge(Integer.parseInt(age));
        user.setName(name);
        ud.insert(user);
        // 给出提示，并跳转到登录页
        out.println("<script>alert('已注册成功，请登录');</script>");
        out.println("3秒后自动跳转到登录页面……");
        response.setHeader("Refresh", "3,url='login.jsp'");
      }
    } else if (action.equals("logout")) {
      // 注销登录，销毁session
      request.getSession().invalidate();
      // 跳转到登录页面，使用location.href跳转回登录页，要不然浏览器路径还是logout.jsp
      response.sendRedirect("login.jsp");
      // out.println("<script>location.href='login.jsp'</script>");
      // request.getRequestDispatcher("login.jsp").forward(request, response);
    } else if (action.equals("addCatalog")) {
      // 添加分类
      CatalogDao cd = new CatalogDao();
      // 用分类名称查数据库，判断分类是否已存在
      String name = request.getParameter("name");
      Catalog byCatalogName = cd.getByCatalogName(name);
      if (byCatalogName != null) {
        out.println("<script>alert('添加失败，已存在同名分类！');location.href='adminListAncientPainting.action';</script>");
      } else {
        Catalog catalog = new Catalog();
        catalog.setName(name);
        cd.insert(catalog);
        out.println("<script>alert('添加成功！');location.href='adminListAncientPainting.action';</script>");
      }
    } else if (action.equals("deleteAncientPainting")) {
      // 删除古画
      AncientPaintingDao ancientPaintingDao = new AncientPaintingDao();
      int id = Integer.parseInt(request.getParameter("id"));
      ancientPaintingDao.deleteById(id);
      // 跳转到列表页
      out.println("<script>alert('删除成功！');location.href='adminListAncientPainting.action';</script>");
    } else if (action.equals("deleteCatalog")) {
      // 删除分类
      AncientPaintingDao ancientPaintingDao = new AncientPaintingDao();
      CatalogDao catalogDao = new CatalogDao();
      int id = Integer.parseInt(request.getParameter("id"));
      // 判断该分类是否有古画使用
      int paintingCount = ancientPaintingDao.getCountByCatalogId(id);
      if (paintingCount > 0) {
        out.println("<script>alert('删除失败，该分类使用中不可删除！');location.href='adminListAncientPainting.action';</script>");
      } else {
        // 如果在古画表中找不到，则可以删除
        catalogDao.deleteById(id);
        out.println("<script>alert('删除成功！');location.href='adminListAncientPainting.action';</script>");
      }
    } else if (action.equals("updateCatalog")) {
      // 更新目录
      int id = Integer.parseInt(request.getParameter("id"));
      String name = request.getParameter("name");
      CatalogDao cd = new CatalogDao();
      Catalog byId = cd.getById(id);
      // 先用id找分类，找不到报错
      if (byId == null) {
        out.println("<script>alert('修改失败，该分类不存在！');location.href='adminListAncientPainting.action';</script>");
      } else {
        Catalog target = new Catalog();
        target.setId(id);
        target.setName(name);
        AncientPaintingDao bd = new AncientPaintingDao();
        // 分类存在，判断分类名是否已存在分类存在，判断分类名是否已存在
        Catalog byCatalogName = cd.getByCatalogName(name);
        if (byCatalogName == null) {
          // 更新分类
          cd.updateById(target);
          // 更新分类后，更新古画表中的分类
          bd.updateAncientPaintingCatalog(target);
          out.println("<script>alert('修改成功！');location.href='adminListAncientPainting.action';</script>");
        } else if (byCatalogName.getId() == id) {
          bd.updateAncientPaintingCatalog(target);
          out.println("<script>alert('修改成功！');location.href='adminListAncientPainting.action';</script>");
        } else if (byCatalogName.getId() != id) {
          // 限制分类不能同名
          out.println("<script>alert('修改失败，已存在同名分类！');location.href='adminListAncientPainting.action';</script>");
        }
      }
    } else if (action.equals("searchAncientPainting")) {
      // 头部搜索古画
      String name = request.getParameter("name");
      String catalogName = request.getParameter("catalogName");
      AncientPaintingDao bd = new AncientPaintingDao();
      // 通过分类名称和古画名称查询古画
      List<AncientPainting> ancientPaintings = bd.searchAncientPaintings(name, catalogName);
      request.setAttribute("ancientPaintings", ancientPaintings);
      User user = (User) session.getAttribute("user");
      // 获取左边的分类
      CatalogDao catalogDao = new CatalogDao();
      List<Catalog> catalogs = catalogDao.getAllCatalogs();
      request.setAttribute("catalogs", catalogs);

      // 如果用户是普通用户，则跳转到普通用户的古画列表页面
      if (user.getRole() == 0) {
        request.getRequestDispatcher("ancient_painting_list.jsp").forward(request, response);
      } else {
        // 如果用户是管理员，则跳转到管理员的古画列表页面
        request.getRequestDispatcher("/admin/admin_list_ancient_painting.jsp").forward(request, response);
      }
    } else if (action.equals("purchaseAncientPainting")) {
      // 购买古画
      String id = request.getParameter("id");
      AncientPaintingDao bd = new AncientPaintingDao();
      int count = 0;
      AncientPainting ancientPainting = bd.getAncientPainting(id);
      List<AncientPainting> cart = (List) session.getAttribute("cart");
      if (cart == null) {
        cart = new ArrayList<>();
        session.setAttribute("number", 0);
        session.setAttribute("cart", cart);
      }
      int flag = 0;
      for (AncientPainting cartAncientPainting : cart) {
        if (ancientPainting.getName().equals(cartAncientPainting.getName())) {
          cartAncientPainting.setCartNum(cartAncientPainting.getCartNum() + 1);
          flag = 1;
        }
      }
      if (flag == 0) {
        ancientPainting.setCartNum(1);
        cart.add(ancientPainting);
      }
      count = (int) session.getAttribute("number");
      session.setAttribute("cart", cart);
      count++;
      session.setAttribute("number", count);
      request.getRequestDispatcher("userListAncientPainting.action").forward(request, response);
    } else if (action.equals("userListAncientPainting")) {
      // 普通用户的古画列表页
      // 获取左边的分类
      CatalogDao catalogDao = new CatalogDao();
      List<Catalog> catalogs = catalogDao.getAllCatalogs();
      request.setAttribute("catalogs", catalogs);
      // 获取右边的古画列表
      AncientPaintingDao bd = new AncientPaintingDao();
      List<AncientPainting> ancientPaintings = bd.getAllAncientPaintings();
      request.setAttribute("ancientPaintings", ancientPaintings);
      request.getRequestDispatcher("ancient_painting_list.jsp").forward(request, response);
    } else if (action.equals("showCart")) {
      request.getRequestDispatcher("cart.jsp").forward(request, response);
    } else if (action.equals("addAncientPaintingView")) {
      // 添加古画页面需要带出左边的分类
      CatalogDao catalogDao = new CatalogDao();
      List<Catalog> catalogs = catalogDao.getAllCatalogs();
      request.setAttribute("catalogs", catalogs);
      request.getRequestDispatcher("/admin/admin_add_ancient_painting.jsp").forward(request, response);
    } else if (action.equals("addAncientPainting")) {
      String name = request.getParameter("name");
      String author = request.getParameter("author");
      String press = request.getParameter("press");
      String price = request.getParameter("price");
      String catalogName = request.getParameter("catalogName");
      String path = request.getParameter("path");

      AncientPainting ancientPainting = new AncientPainting();
      ancientPainting.setName(name);
      ancientPainting.setAuthor(author);
      ancientPainting.setPress(press);
      ancientPainting.setPrice((float) Double.parseDouble(price));
      ancientPainting.setPath(path);
      // 查找目录
      CatalogDao catalogDao = new CatalogDao();
      // 如果有目录，则设置目录名
      // 没有目录，则设置目录名为-
      Catalog catalog = catalogDao.getByCatalogName(catalogName);
      ancientPainting.setCatalogName(catalog == null ? "-" : catalogName);
      ancientPainting.setCatalogId(catalog == null ? -1 : catalog.getId());
      AncientPaintingDao ancientPaintingDao = new AncientPaintingDao();
      boolean flag = ancientPaintingDao.addAncientPainting(ancientPainting);
      if (flag) {
        // 新增数据后，重新查最新的数据，获取上传的图片path更新到数据上
        Part image = request.getPart("image");
        String fileName = getFileName(image);
        if (!fileName.isEmpty()) {
          AncientPainting lastAncientPainting = ancientPaintingDao.getLastAncientPainting();
          fileName = lastAncientPainting.getId() + "-" + UUID.randomUUID() + fileName;
          writeTo(request, fileName, image);
          String newPath = "images/" + fileName;
          lastAncientPainting.setPath(newPath);
          ancientPaintingDao.updateAncientPainting(lastAncientPainting);
        }
        out.println("<script>alert('添加成功！');location.href='adminListAncientPainting.action';</script>");
      } else {
        out.println("<script>alert('古画添加失败，请重新添加');location.href='adminListAncientPainting.action';</script>");
      }
    } else if (action.equals("adminListAncientPainting")) {
      AncientPaintingDao bd = new AncientPaintingDao();
      List<AncientPainting> ancientPaintings = bd.getAllAncientPaintings();
      CatalogDao catalogDao = new CatalogDao();
      List<Catalog> catalogs = catalogDao.getAllCatalogs();
      request.setAttribute("catalogs", catalogs);
      request.setAttribute("ancientPaintings", ancientPaintings);
      request.getRequestDispatcher("/admin/admin_list_ancient_painting.jsp").forward(request, response);
    } else if (action.equals("updateAncientPaintingView")) {
      String id = request.getParameter("id");
      AncientPaintingDao ancientPaintingDao = new AncientPaintingDao();
      AncientPainting ancientPainting = ancientPaintingDao.getAncientPainting(id);
      // 查找所有目录，给updateAncientPainting.jsp界面的下拉框提供分类的数据
      CatalogDao catalogDao = new CatalogDao();
      List<Catalog> catalogs = catalogDao.getAllCatalogs();
      request.setAttribute("catalogs", catalogs);
      request.setAttribute("ancientPainting", ancientPainting);
      request.getRequestDispatcher("/admin/admin_update_ancient_painting.jsp").forward(request, response);
    } else if (action.equals("updateAncientPainting")) {
      String name = request.getParameter("name");
      String author = request.getParameter("author");
      String press = request.getParameter("press");
      String price = request.getParameter("price");
      String catalogName = request.getParameter("catalogName");
      String id = request.getParameter("id");
      AncientPaintingDao ancientPaintingDao = new AncientPaintingDao();
      // 先获取要更新的数据，如果不存在直接报错返回
      AncientPainting target = ancientPaintingDao.getAncientPainting(id);
      if (target == null) {
        out.println("<script>alert('修改失败');location.href='adminListAncientPainting.action';</script>");
        return;
      }
      // 更新数据
      target.setName(name);
      target.setAuthor(author);
      target.setPress(press);
      target.setId(Integer.parseInt(id));
      target.setPrice(Float.parseFloat(price));
      Part image = request.getPart("image");
      String fileName = getFileName(image);
      // 如果有上传图片，则覆盖，否则保持旧数据
      if (!fileName.isEmpty()) {
        fileName = id + "-" + UUID.randomUUID() + fileName;
        writeTo(request, fileName, image);
        String path = "images/" + fileName;
        target.setPath(path);
      }
      // 查找目录
      CatalogDao catalogDao = new CatalogDao();
      // 如果有目录，则设置目录名
      // 没有目录，则设置目录名为-
      Catalog catalog = catalogDao.getByCatalogName(catalogName);
      target.setCatalogName(catalog == null ? "-" : catalogName);
      target.setCatalogId(catalog == null ? -1 : catalog.getId());
      int flag = ancientPaintingDao.updateAncientPainting(target);
      if (flag == 1) {
        out.println("<script>alert('修改成功');location.href='adminListAncientPainting.action';</script>");
      } else {
        out.println("<script>alert('修改失败');location.href='adminListAncientPainting.action';</script>");
      }
    }
  }

  private String getFileName(Part part) {
    String head = part.getHeader("Content-Disposition");
    String fileName = head.substring(head.indexOf("filename=\"") + 10, head.lastIndexOf("\""));
    return fileName;
  }

  private void writeTo(HttpServletRequest request, String fileName, Part part) throws IOException {
    String rootPath = request.getServletContext().getRealPath("/images");
    File path = new File(rootPath);
    if (!path.exists()) {
      boolean status = path.mkdirs();
      if (status) {
        System.out.println("Created directories: " + path.getAbsolutePath());
      }
    }
    InputStream in = part.getInputStream();
    OutputStream out = Files.newOutputStream(Paths.get(rootPath + File.separator + fileName));
    byte[] b = new byte[1024];
    int length = -1;
    while ((length = in.read(b)) != -1) {
      out.write(b, 0, length);
    }
    in.close();
    out.close();
  }

  @Override
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    this.doGet(request, response);
  }
}
